package com.huangd.platform.common.utils;

import com.huangd.platform.common.exception.RRException;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigDecimal;
import java.nio.channels.FileChannel;
import java.util.Collections;
import java.util.Date;
import java.util.Stack;

/**
 **
 */
public class FileUtils {

	public static void clearDirectory(File targetDirectory) {
		final Stack<File> directories = new Stack<File>();
		final Stack<File> files = new Stack<File>();
		final FileFilter directoryFilter = new FileFilter() {
			@Override
			public boolean accept(File file) {
				if (file.isDirectory()) {
					return true;
				}
				files.push(file);
				return false;
			}
		};
		directories.push(targetDirectory);
		while (!directories.isEmpty()) {
			final File directory = directories.pop();
			files.push(directory);
			Collections.addAll(directories, directory.listFiles(directoryFilter));
		}
		for (File file : files) {
			file.delete();
		}
	}

	public static long copyFile(int cacheSize, File from, File to) throws IOException {
		final long time = new Date().getTime();

		final FileInputStream in = new FileInputStream(from);
		final FileOutputStream out = new FileOutputStream(to);
		final FileChannel inChannel = in.getChannel();
		final FileChannel outChannel = out.getChannel();

		int length;
		while (true) {
			if (inChannel.position() == inChannel.size()) {
				inChannel.close();
				outChannel.close();
				in.close();
				out.close();
				return new Date().getTime() - time;
			}
			if ((inChannel.size() - inChannel.position()) < cacheSize) {
				length = (int) (inChannel.size() - inChannel.position());
			} else {
				length = cacheSize;
			}
			inChannel.transferTo(inChannel.position(), length, outChannel);
			inChannel.position(inChannel.position() + length);
		}
	}

	public static void closeReader(Reader inputStream) {
		if (inputStream != null) {
			try {
				inputStream.close();
			} catch (Exception exception) {
				exception.printStackTrace();
			}
		}
	}

	public static void closeWriter(Writer outputStream) {
		if (outputStream != null) {
			try {
				outputStream.close();
			} catch (Exception exception) {
				exception.printStackTrace();
			}
		}
	}

	public static void closeInputStream(InputStream inputStream) {
		if (inputStream != null) {
			try {
				inputStream.close();
			} catch (Exception exception) {
				exception.printStackTrace();
			}
		}
	}

	public static void closeOutputStream(OutputStream outputStream) {
		if (outputStream != null) {
			try {
				outputStream.close();
			} catch (Exception exception) {
				exception.printStackTrace();
			}
		}
	}

	public static String getFormatSize(long size) {
		double kiloByte = size / 1024d;
		if (kiloByte < 1) {
			return size + "B";
		}

		double megaByte = kiloByte / 1024d;
		if (megaByte < 1) {
			BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
			return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
		}

		double gigaByte = megaByte / 1024;
		if (gigaByte < 1) {
			BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
			return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
		}

		double teraBytes = gigaByte / 1024;
		if (teraBytes < 1) {
			BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
			return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB";
		}
		BigDecimal result4 = new BigDecimal(teraBytes);
		return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
	}

	public static byte[] toBytes(Object object) {
		ByteArrayOutputStream baos = null;
		ObjectOutputStream oos = null;
		try {
			baos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(baos);
			oos.writeObject(object);
			byte[] bytes = baos.toByteArray();
			return bytes;
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				oos.close();
			} catch (Exception e) {
			}
		}
	}

	public static void toFile(Object object, File file) {
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try {
			fos = new FileOutputStream(file);
			oos = new ObjectOutputStream(fos);
			oos.writeObject(object);
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				oos.close();
			} catch (Exception e) {
			}
		}
	}

	public static Object toObject(byte[] bytes) {
		ByteArrayInputStream bais = null;
		ObjectInputStream ois = null;
		try {
			bais = new ByteArrayInputStream(bytes);
			ois = new ObjectInputStream(bais);
			Object object = ois.readObject();
			return object;
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				ois.close();
			} catch (Exception e) {
			}
		}
	}

	public static Object toObject(File file) {
		FileInputStream fis = null;
		ObjectInputStream ois = null;
		try {
			fis = new FileInputStream(file);
			ois = new ObjectInputStream(fis);
			Object object = ois.readObject();
			return object;
		} catch (Exception e) {
			throw new RuntimeException("反序列化文件失败:" + file.getAbsolutePath(), e);
		} finally {
			try {
				ois.close();
			} catch (Exception e) {
			}
		}
	}


	/**
	 * MultipartFile 转 File
	 *
	 * @param file
	 * @throws Exception
	 */
	public static File multipartFileToFile(MultipartFile file) {

		File toFile = null;
		try {
			if (file.equals("") || file.getSize() <= 0) {
				file = null;
			} else {
				InputStream ins = null;
				ins = file.getInputStream();
				toFile = new File(file.getOriginalFilename());
				inputStreamToFile(ins, toFile);
				ins.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new RRException("文件出错");
		}
		return toFile;
	}


	//获取流文件
	private static void inputStreamToFile(InputStream ins, File file) {
		try {
			OutputStream os = new FileOutputStream(file);
			int bytesRead = 0;
			byte[] buffer = new byte[8192];
			while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			ins.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 删除本地临时文件
	 * @param file
	 */
	public static void delteTempFile(File file) {
		if (file != null) {
			File del = new File(file.toURI());
			del.delete();
		}
	}
}
